/**
 * Fichier Service.java : Définition de classe fr.unice.gnpt.core.Service :
 * Service pouvant être assigné à un enseignant.
 * 
 * Auteurs : Groupe GNPT : Gastinel, Nicolas, Pellegrino, Trovato
 */
package fr.unice.gnpt.core;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Version;

import com.db4o.activation.ActivationPurpose;
import com.db4o.activation.Activator;
import com.db4o.ta.Activatable;

/**
 * Classe abstraite gérant les services pouvant être assignés à un enseignant.
 * <p>
 * Un service est obligatoirement associé à un enseignant et contient un nombre
 * d'heure de travail demandé calculé en nombre d'heures de travaux dirigés
 * équivalent.
 * 
 * @author gnpt
 * @version 0.0.2
 */
@Entity
@NamedQueries( {
		@NamedQuery(name = "Service.findAllServices", query = "SELECT e.services FROM Enseignant e"),
		@NamedQuery(name = "Service.findAllEnseignements", query = "SELECT c.enseignements FROM Cours c") })
@Table(name = "Service_gnpt")
public abstract class Service implements Activatable, Comparable<Service> {
	/**
	 * Représente un numéro de version (incrémenté à chaque modification),
	 * utilisé (par JPA) pour savoir si l’état d’une entité a été modifié entre
	 * 2 moments différents.
	 */
	private int version;
	/**
	 * Identifiant unique utilisé par JPA.
	 */
	private int id;
	/**
	 * Nombre d'heures de TD équivalent.
	 */
	private int nbHeuresEquivalent;
	/**
	 * Enseignant assigné au service.
	 */
	private Enseignant enseignant;
	/**
	 * Validité du service.
	 */
	private boolean valide = false;
	
	private transient Activator _activator = null;

	/**
	 * Constructeur par défaut.
	 * 
	 * @param enseignant
	 *            l'enseignant associé au service.
	 */
	public Service(Enseignant enseignant) {
		this.enseignant = enseignant;
	}

	/**
	 * Constructeur par défaut.
	 */
	public Service() {
		super();
	}

	/**
	 * Accesseur pour l'identifiant unique caractérisant un enseignant.
	 * 
	 * @return l'identifiant unique caractérisant un enseignant.
	 */
	@Id
	@GeneratedValue
	public int getId() {
		this.activate(ActivationPurpose.READ);
		return this.id;
	}

	/**
	 * Accesseur pour le nombre d'heures de TD equivalent associé au service.
	 * 
	 * @return le nombre d'heures de TD equivalent associé au service.
	 */
	public int getNbHeuresEquivalent() {
		this.activate(ActivationPurpose.READ);
		return this.nbHeuresEquivalent;
	}

	/**
	 * Accesseur pour l'enseignant associé au service. On utilise la propriété
	 * CascadeType.REFRESH car les services sont crées depuis Enseignant, donc
	 * l'enseignant est déjà persistant à ce stade.
	 * 
	 * @return l'enseignant associé au service.
	 */
	@ManyToOne(cascade = CascadeType.REFRESH)
	public Enseignant getEnseignant() {
		this.activate(ActivationPurpose.READ);
		return this.enseignant;
	}

	/**
	 * Accesseur pour le numéro de version (incrémenté à chaque modification),
	 * utilisé (par JPA) pour savoir si l’état d’une entité a été modifié entre
	 * 2 moments différents.
	 * 
	 * @return le numéro de version.
	 */
	@Version
	public int getVersion() {
		this.activate(ActivationPurpose.READ);
		return this.version;
	}

	/**
	 * Mutateur pour le numéro de version courant.
	 * 
	 * @param version
	 *            le nouveau numéro de version.
	 */
	public void setVersion(int version) {
		this.activate(ActivationPurpose.WRITE);
		this.version = version;
	}

	/**
	 * Mutateur pour l'identifiant unique caractérisant un enseignant.
	 * 
	 * @param id
	 *            le nouveau identifiant unique caractérisant un enseignant.
	 */
	public void setId(int id) {
		this.activate(ActivationPurpose.WRITE);
		this.id = id;
	}

	/**
	 * Mutateur pour le nombre d'heures équivalent en heures de TD associé au
	 * service.
	 * 
	 * @param nbHeuresEquivalent
	 *            le nombre d'heures équivalent en heures de TD associé au
	 *            service.
	 */
	public void setNbHeuresEquivalent(int nbHeuresEquivalent) {
		this.activate(ActivationPurpose.WRITE);
		this.nbHeuresEquivalent = nbHeuresEquivalent;
	}

	/**
	 * Mutateur pour l'enseignant associé au service.
	 * 
	 * @param enseignant
	 *            le nouveau enseignant associé au service.
	 */
	public void setEnseignant(Enseignant enseignant) {
		this.activate(ActivationPurpose.WRITE);
		this.enseignant = enseignant;
	}

	/**
	 * Accesseur pour la validité du service.
	 * 
	 * @return le valide
	 */
	public boolean getValide() {
		this.activate(ActivationPurpose.READ);
		return this.valide;
	}

	/**
	 * Mutateur privé pour la validité du service.
	 * 
	 * @param valide
	 *            le nouvel état.
	 */
	private void setValide(boolean valide) {
		this.activate(ActivationPurpose.WRITE);
		this.valide = valide;
	}

	/**
	 * Accesseur à la validité du service.
	 * 
	 * @return le valide.
	 */
	public boolean estValide() {
		this.activate(ActivationPurpose.READ);
		return this.valide;
	}

	/**
	 * Méthode appelée par le coordonateur qui valide le service.
	 * 
	 * @throws ServiceDejaValideException
	 *             il faut invalider le service avant.
	 */
	public void valider() throws ServiceDejaValideException {
		this.activate(ActivationPurpose.READ);
		if (!this.valide)
			this.setValide(true);
		else
			throw new ServiceDejaValideException();
	}

	/**
	 * Invalide le service
	 */
	public void invalider() {
		this.activate(ActivationPurpose.WRITE);
		this.valide = false;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		this.activate(ActivationPurpose.READ);
		return this.getClass().getSimpleName() + " pour '" + this.getEnseignant()
				+ "'";
	}

	/**
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Service s) {
		this.activate(ActivationPurpose.READ);
		return this.getEnseignant().compareTo(s.getEnseignant());
	}

	/**
	 * @see com.db4o.ta.Activatable#activate(com.db4o.activation.ActivationPurpose)
	 */
	@Override
	public void activate(ActivationPurpose ap) {
		if (this._activator != null)
			this._activator.activate(ap);
	}

	/**
	 * @see com.db4o.ta.Activatable#bind(com.db4o.activation.Activator)
	 */
	@Override
	public void bind(Activator activator) {
		this._activator = activator;
	}
}
